package com.qing.expert.modules.user.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qing.expert.common.config.WxConfig;
import com.qing.expert.common.exception.BusinessException;
import com.qing.expert.common.utils.RedisUtils;
import com.qing.expert.modules.user.entity.BalanceRecord;
import com.qing.expert.modules.user.entity.User;
import com.qing.expert.modules.user.entity.UserFavorite;
import com.qing.expert.modules.user.mapper.BalanceRecordMapper;
import com.qing.expert.modules.user.mapper.UserFavoriteMapper;
import com.qing.expert.modules.user.mapper.UserMapper;
import com.qing.expert.modules.user.service.UserService;
import com.qing.expert.modules.user.vo.request.BalanceRequest;
import com.qing.expert.modules.user.vo.request.UserUpdateRequest;
import com.qing.expert.modules.user.vo.response.BalanceRecordVO;
import com.qing.expert.modules.user.vo.response.FavoriteGoodsVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private WxConfig wxConfig;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private UserFavoriteMapper userFavoriteMapper;

    @Resource
    private BalanceRecordMapper balanceRecordMapper;

    @Override
    public User wxLogin(String code, String nickName, String avatarUrl) {
        log.info("微信登录开始，code: {}, nickName: {}, avatarUrl: {}", code, nickName, avatarUrl);

        // 1. 请求微信服务器获取openid
        String url = String.format(
                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                wxConfig.getAppId(), wxConfig.getAppSecret(), code);

        String result = HttpUtil.get(url);
        log.info("微信登录响应结果：{}", result);

        JSONObject json = JSONUtil.parseObj(result);

        // 2. 处理微信接口响应
        if (json.containsKey("errcode") && json.getInt("errcode") != 0) {
            log.error("微信登录失败：{}", json.getStr("errmsg"));
            throw new BusinessException("微信登录失败：" + json.getStr("errmsg"));
        }

        String openid = json.getStr("openid");
        if (openid == null) {
            log.error("获取openid失败");
            throw new BusinessException("获取openid失败");
        }

        // 3. 查询或注册用户
        User user = getOne(new LambdaQueryWrapper<User>()
                .eq(User::getOpenid, openid));

        if (user == null) {
            log.info("新用户注册，openid: {}", openid);
            user = new User()
                    .setUserId("U" + IdUtil.getSnowflakeNextId())
                    .setOpenid(openid)
                    .setNickname(nickName)
                    .setAvatar(avatarUrl)
                    .setRole(1)
                    .setBalance(0.0)
                    .setStatus(1);
            save(user);
        } else {
            log.info("用户登录，userId: {}", user.getUserId());
            // 更新用户信息
            if (nickName != null || avatarUrl != null) {
                User updateUser = new User();
                updateUser.setUserId(user.getUserId());
                if (nickName != null) {
                    updateUser.setNickname(nickName);
                }
                if (avatarUrl != null) {
                    updateUser.setAvatar(avatarUrl);
                }
                updateById(updateUser);
                // 重新获取最新的用户信息
                user = getById(user.getUserId());
            }
            // 检查用户状态
            if (user.getStatus() != 1) {
                log.error("用户已被禁用，userId: {}", user.getUserId());
                throw new BusinessException("账号已被禁用");
            }
        }

        // 4. 将用户信息存入Redis，用于在线状态判断
        String redisKey = "user:online:" + user.getUserId();
        redisUtils.set(redisKey, "1", 24, TimeUnit.HOURS);

        log.info("用户登录成功，userId: {}", user.getUserId());
        return user;
    }

    @Override
    public void logout(String userId) {
        log.info("用户登出开始，userId: {}", userId);

        // 1. 从Redis中删除用户在线状态
        String redisKey = "user:online:" + userId;
        redisUtils.delete(redisKey);

        log.info("用户登出成功，userId: {}", userId);
    }

    @Override
    public void updateUserInfo(String userId, UserUpdateRequest request) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setNickname(request.getNickName())
                .setAvatar(request.getAvatarUrl())
                .setPhone(request.getPhone())
                .setWechat(request.getWxAccount());

        this.updateById(user);
        log.info("用户[{}]更新信息成功", userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recharge(String userId, BalanceRequest request) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 1. 创建充值记录
        BalanceRecord record = new BalanceRecord()
                .setUserId(userId)
                .setType(1) // 1=充值
                .setAmount(request.getAmount())
                .setStatus(0) // 0=处理中
                .setRemark("用户充值");
        balanceRecordMapper.insert(record);

        // TODO: 调用支付接口

        // 2. 更新用户余额(模拟支付成功)
        user.setBalance(user.getBalance() + request.getAmount().doubleValue());
        this.updateById(user);

        // 3. 更新充值记录状态
        record.setStatus(1); // 1=成功
        balanceRecordMapper.updateById(record);

        log.info("用户[{}]充值[{}]元成功", userId, request.getAmount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void withdraw(String userId, BalanceRequest request) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (user.getBalance() < request.getAmount().doubleValue()) {
            throw new BusinessException("余额不足");
        }

        // 1. 创建提现记录
        BalanceRecord record = new BalanceRecord()
                .setUserId(userId)
                .setType(2) // 2=提现
                .setAmount(request.getAmount())
                .setStatus(0) // 0=处理中
                .setRemark("用户提现");
        balanceRecordMapper.insert(record);

        // 2. 冻结用户余额
        user.setBalance(user.getBalance() - request.getAmount().doubleValue());
        this.updateById(user);

        log.info("用户[{}]申请提现[{}]元", userId, request.getAmount());
    }

    @Override
    public Page<FavoriteGoodsVO> getFavorites(String userId, Integer page, Integer size) {
        return userFavoriteMapper.selectFavoriteGoods(new Page<>(page, size), userId);
    }

    @Override
    public void addFavorite(String userId, String goodsId) {
        // 1. 检查是否已收藏
        Long count = userFavoriteMapper.selectCount(
                new LambdaQueryWrapper<UserFavorite>()
                        .eq(UserFavorite::getUserId, userId)
                        .eq(UserFavorite::getGoodsId, goodsId));
        if (count > 0) {
            throw new BusinessException("已收藏该商品");
        }

        // 2. 添加收藏
        UserFavorite favorite = new UserFavorite()
                .setUserId(userId)
                .setGoodsId(goodsId);
        userFavoriteMapper.insert(favorite);

        log.info("用户[{}]收藏商品[{}]成功", userId, goodsId);
    }

    @Override
    public void removeFavorite(String userId, String goodsId) {
        userFavoriteMapper.delete(
                new LambdaQueryWrapper<UserFavorite>()
                        .eq(UserFavorite::getUserId, userId)
                        .eq(UserFavorite::getGoodsId, goodsId));

        log.info("用户[{}]取消收藏商品[{}]", userId, goodsId);
    }

    @Override
    public Page<BalanceRecordVO> getBalanceRecords(String userId, Integer page, Integer size) {
        return balanceRecordMapper.selectBalanceRecords(new Page<>(page, size), userId);
    }
}